iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
IT Operation

AI 輔助開發下,測試如何保住品質防線系列 第 18

Day 18:沒有 PHPStan,型別錯誤靠什麼擋?答案:目前沒有

  • 分享至 

  • xImage
  •  

前言:這個套件有在用靜態分析工具嗎?

「這個套件寫得算工整,應該有在用靜態分析工具吧?」

沒有。翻遍整個專案,找不到 phpstan.neonpsalm.xml 或任何等效設定檔。今天先誠實面對這件事,順便看一個更嚴重、跟型別無關但同樣屬於「沒人在把關」的發現。

今日目標

  • 確認這個套件目前沒有導入任何靜態分析工具
  • 理解「靠測試抓型別錯誤」跟「靠靜態分析在寫的當下就攔截」的差異與各自的成本
  • 看一個真實跑出來的數字:依賴鏈裡累積了多少已知安全性風險
  • 為明天的 PHPStan 實測結果先鋪好背景

目前的型別安全防線:只有測試,而且只在執行到的分支才擋得住

沒有 PHPStan/Psalm,代表這個套件裡任何型別不一致的問題(例如某個方法宣告要回傳一種型別,實際卻回傳了另一種),只能靠三件事之一被發現:

  1. 測試剛好覆蓋到那個分支,斷言剛好夠嚴謹去檢查型別
  2. 使用者在自己的專案裡用到那個方法時,PHP 執行期丟出型別錯誤
  3. 沒有人發現,程式碼繼續帶著這個問題運作下去

跟靜態分析工具的差別在於:靜態分析是在你寫程式碼的當下(或 CI 跑的當下)就分析整份原始碼找出型別不一致,不需要真的執行到那條路徑;測試則永遠只能驗證「你寫了測試去驗證的那個情境」,沒被測到的分支,型別問題就完全不會浮現。

這不是「這個套件比較差」,是很多專案的常態

沒有 PHPStan/Psalm 的專案非常普遍,尤其是這種規模不大、由個人或小團隊維護的驅動套件。導入靜態分析工具本身有成本:選規則等級、處理既有程式碼觸發的第一批警告、決定哪些警告可以先忽略——這些都需要一次性的投入,對一個已經穩定運作好幾年的套件來說,投入的誘因通常要等到「真的出過一次型別相關的 bug」才會浮現。

一個更嚴重、但性質完全不同的發現:依賴鏈的安全性風險

型別安全不是唯一沒被靜態工具把關的面向。用 composer audit(Composer 內建、檢查已安裝依賴是否命中已知安全性公告的指令)在一份本機暫存複本上實際跑一次,結果是:

17 個安全性風險通報,影響 6 個套件,多數集中在 guzzlehttp/guzzle——例如一個被標記為高風險等級的「不合規範的 host 名稱可以繞過主機檢查」問題,以及好幾個中風險等級、跟 cookie/導向處理相關的問題(例如 cookie 的網域範圍沒有被正確限制、URI 片段被意外洩漏到重新導向的 Referer 標頭裡)。這些不是 omnipay-ecpay 自己寫的程式碼有問題,是它依賴鏈裡的間接套件版本太舊,多年累積下來的已知漏洞修補都還沒吃到。

型別錯誤跟安全性風險是兩種完全不同的問題,但共通點是:兩者都不會在「跑測試」這個層次被發現。 測試驗證的是「這個功能符合預期行為」,不會去檢查「這個依賴的版本是不是帶著一個三年前就公開的已知漏洞」。這正是為什麼品質防線不能只靠測試——測試回答不了的問題,需要別的工具去補。

❌ vs ✅:只靠測試 vs 多一層自動化檢查

❌ 現況:只有 CI 跑測試,沒有任何工具檢查依賴版本的安全性
CI workflow:composer install → phpunit --no-coverage

依賴鏈裡累積了多少已知漏洞,完全沒有自動化的方式會被發現,
除非剛好有人手動想到要跑一次 composer audit
✅ 加一個步驟,讓已知漏洞至少會被看見
CI workflow:composer install → composer audit → phpunit --no-coverage

一旦某個依賴版本命中已知漏洞公告,CI 至少會顯示出來,
即使一開始選擇不讓它擋住建置(先觀察,之後再決定要不要設成阻斷)

composer audit 是 Composer 內建指令,不需要額外安裝套件,加進 CI 幾乎是零成本的一步——這也是為什麼「沒有導入」比較像是「沒人想到要加」,而不是「加了會很麻煩」。

今日思考題

你維護的專案,上一次跑 composer audit(或其他語言生態系的等效指令,例如 npm auditpip-audit)是什麼時候?如果從來沒跑過,現在花兩分鐘跑一次,會不會也發現幾個累積很久的已知風險?

今日重點回顧

  • 這個套件目前沒有導入任何靜態分析工具,型別問題只能靠測試覆蓋到的分支被動發現
  • 測試驗證的是「行為符不符合預期」,回答不了「依賴版本是否帶著已知漏洞」這類問題
  • composer audit 實測發現 17 個安全性風險通報,集中在依賴鏈裡版本過舊的 guzzlehttp/guzzle
  • composer audit 這種幾乎零成本的檢查加進 CI,能讓已知風險至少「被看見」

明日預告

明天正式在一份暫存複本上裝起 PHPStan,實際跑一次 level 5 掃描,看看這個「沒用新語法、看起來很工整」的套件,第一次被靜態分析工具照過後,會冒出什麼樣的錯誤——包括一個因為打字打錯而鬧的笑話。


上一篇
Day 17:徽章連到的 CI 服務,幾年前就沒人在用了
下一篇
Day 19:第一次跑 PHPStan,抓到一個打字打錯的烏龍
系列文
AI 輔助開發下,測試如何保住品質防線19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言